@@ -202,12 +202,12 @@ module LiquidInterpolatable |
||
202 | 202 |
end |
203 | 203 |
end |
204 | 204 |
|
205 |
- def regex_replace(input, regex, replacement = ''.freeze) |
|
206 |
- input.to_s.gsub(Regexp.new(regex), replacement.to_s) |
|
205 |
+ def regex_replace(input, regex, replacement = nil) |
|
206 |
+ input.to_s.gsub(Regexp.new(regex), unescape_replacement(replacement.to_s)) |
|
207 | 207 |
end |
208 | 208 |
|
209 |
- def regex_replace_first(input, regex, replacement = ''.freeze) |
|
210 |
- input.to_s.sub(Regexp.new(regex), replacement.to_s) |
|
209 |
+ def regex_replace_first(input, regex, replacement = nil) |
|
210 |
+ input.to_s.sub(Regexp.new(regex), unescape_replacement(replacement.to_s)) |
|
211 | 211 |
end |
212 | 212 |
|
213 | 213 |
private |
@@ -221,6 +221,37 @@ module LiquidInterpolatable |
||
221 | 221 |
Logger.new(STDERR) |
222 | 222 |
end |
223 | 223 |
end |
224 |
+ |
|
225 |
+ BACKSLASH = "\\".freeze |
|
226 |
+ |
|
227 |
+ UNESCAPE = { |
|
228 |
+ "a" => "\a", |
|
229 |
+ "b" => "\b", |
|
230 |
+ "e" => "\e", |
|
231 |
+ "f" => "\f", |
|
232 |
+ "n" => "\n", |
|
233 |
+ "r" => "\r", |
|
234 |
+ "s" => " ", |
|
235 |
+ "t" => "\t", |
|
236 |
+ "v" => "\v", |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ def unescape_replacement(s) |
|
240 |
+ s.gsub(/\\(?:([\d+&`'\\]|k<\w+>)|u\{([[:xdigit:]]+)\}|x([[:xdigit:]]{2})|(.))/) { |
|
241 |
+ if c = $1 |
|
242 |
+ BACKSLASH + c |
|
243 |
+ elsif c = ($2 && [$2.to_i(16)].pack('U')) || |
|
244 |
+ ($3 && [$3.to_i(16)].pack('C')) |
|
245 |
+ if c == BACKSLASH |
|
246 |
+ BACKSLASH + c |
|
247 |
+ else |
|
248 |
+ c |
|
249 |
+ end |
|
250 |
+ else |
|
251 |
+ UNESCAPE[$4] || $4 |
|
252 |
+ end |
|
253 |
+ } |
|
254 |
+ end |
|
224 | 255 |
end |
225 | 256 |
Liquid::Template.register_filter(LiquidInterpolatable::Filters) |
226 | 257 |
|
@@ -187,6 +187,12 @@ describe LiquidInterpolatable::Filters do |
||
187 | 187 |
agent.options['cleaned'] = '{{ something | regex_replace_first: "\S+bar", "foobaz" }}' |
188 | 188 |
expect(agent.interpolated['cleaned']).to eq('foobaz foobar') |
189 | 189 |
end |
190 |
+ |
|
191 |
+ it 'should support escaped characters' do |
|
192 |
+ agent.interpolation_context['something'] = "foo\\1\n\nfoo\\bar\n\nfoo\\baz" |
|
193 |
+ agent.options['test'] = "{{ something | regex_replace_first: '\\\\(\\w{2,})', '\\1\\\\' | regex_replace_first: '\\n+', '\\n' }}" |
|
194 |
+ expect(agent.interpolated['test']).to eq("foo\\1\nfoobar\\\n\nfoo\\baz") |
|
195 |
+ end |
|
190 | 196 |
end |
191 | 197 |
|
192 | 198 |
describe 'regex_replace' do |
@@ -197,5 +203,11 @@ describe LiquidInterpolatable::Filters do |
||
197 | 203 |
agent.options['cleaned'] = '{{ something | regex_replace: "\S+bar", "foobaz" }}' |
198 | 204 |
expect(agent.interpolated['cleaned']).to eq('foobaz foobaz') |
199 | 205 |
end |
206 |
+ |
|
207 |
+ it 'should support escaped characters' do |
|
208 |
+ agent.interpolation_context['something'] = "foo\\1\n\nfoo\\bar\n\nfoo\\baz" |
|
209 |
+ agent.options['test'] = "{{ something | regex_replace: '\\\\(\\w{2,})', '\\1\\\\' | regex_replace: '\\n+', '\\n' }}" |
|
210 |
+ expect(agent.interpolated['test']).to eq("foo\\1\nfoobar\\\nfoobaz\\") |
|
211 |
+ end |
|
200 | 212 |
end |
201 | 213 |
end |